/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
/* Definitions for Task_ADC */
osThreadId_t Task_ADCHandle;
const osThreadAttr_t Task_ADC_attributes = {
  .name = "Task_ADC",
  .stack_size = 256 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for Task_Info */
osThreadId_t Task_InfoHandle;
const osThreadAttr_t Task_Info_attributes = {
  .name = "Task_Info",
  .stack_size = 256 * 4,
  .priority = (osPriority_t) osPriorityLow,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void AppTask_ADC(void *argument);
void AppTask_Info(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of Task_ADC */
  Task_ADCHandle = osThreadNew(AppTask_ADC, NULL, &Task_ADC_attributes);

  /* creation of Task_Info */
  Task_InfoHandle = osThreadNew(AppTask_Info, NULL, &Task_Info_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_AppTask_ADC */
/**
  * @brief  Function implementing the Task_ADC thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_AppTask_ADC */
void AppTask_ADC(void *argument)
{
  /* USER CODE BEGIN AppTask_ADC */
  TickType_t pxPreviousWakeTime = xTaskGetTickCount();
  /* Infinite loop */
  for(;;)
  {
      HAL_ADC_Start(&hadc1);
      if(HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) {
          uint32_t adcValue = HAL_ADC_GetValue(&hadc1);
          uint32_t adcVoltage = (adcValue * 3300) / 4096;
          printf("ADC Voltage(mV): %lu  \n", adcVoltage);
      }
      vTaskDelayUntil(&pxPreviousWakeTime, pdMS_TO_TICKS(500));
  }
  /* USER CODE END AppTask_ADC */
}

/* USER CODE BEGIN Header_AppTask_Info */
/**
* @brief Function implementing the Task_Info thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_AppTask_Info */
void AppTask_Info(void *argument)
{
  /* USER CODE BEGIN AppTask_Info */
    TaskHandle_t taskHandle;
    TaskStatus_t taskInfo;
    BaseType_t getFreeStackSpace = pdTRUE;
    eTaskState taskState;
    vTaskGetInfo( taskHandle, &taskInfo, getFreeStackSpace,  taskState);

    taskENTER_CRITICAL();
    printf("Task Info: \n");
    printf("Task Name: %s \n", taskInfo.pcTaskName);                    //任务名称
    printf("Task Number: %lu \n", taskInfo.xTaskNumber);                //任务编号
    printf("Task State: %d \n", taskInfo.eCurrentState);                //任务状态
    printf("Task Priority: %lu \n", taskInfo.uxCurrentPriority);        //优先级
    printf("Task Stack High Water Mark: %d(Word) \n", taskInfo.usStackHighWaterMark); //任务栈剩余空间

    printf("High Water Mark of tasks \n");                              //任务栈剩余空间
    taskHandle = xTaskGetIdleTaskHandle();
    printf("Idle Task = %lu \n", uxTaskGetStackHighWaterMark(taskHandle));      //空闲任务栈剩余空间
    printf("Task_ADC = %lu \n", uxTaskGetStackHighWaterMark(Task_ADCHandle));   //任务ADC栈剩余空间
    printf("Task_Info = %lu \n", uxTaskGetStackHighWaterMark(Task_InfoHandle)); //任务Info栈剩余空间

    printf("uxTaskGetNumberOfTasks() = %d \n", uxTaskGetNumberOfTasks());  //任务数量
    char pcWriteBuffer[300];
    vTaskList(pcWriteBuffer);                                          //任务列表
    printf("Task List: \n%s", pcWriteBuffer);
    taskEXIT_CRITICAL();
  /* Infinite loop */
  for(;;) {
      for (uint8_t i = 0; i < 10; ++i) {
          LED1_Toggle();
          vTaskDelay(pdMS_TO_TICKS(300));
      }
      break;
  }

    printf("Task_Info is deleted\n");
  vTaskDelete(NULL);
  /* USER CODE END AppTask_Info */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

